/******************************************************************************
 * program:     rasimg library                                                *
 * function:    Mask filtering image.                                         *
 * modul:       mask.cc                                                       *
 * licency:     GPL or LGPL                                                   *
 ******************************************************************************/
#include <stddef.h>
#include <stdio.h>

#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#include "typedfs.h"
#include "image.h"
#include "ras_prot.h"
#include "imageop.h"

#include <matrix.h>


//#ifdef RasImg
//#include <alloc.h>

const char *GetExtension(const char *FullName)
{
const char *NameStep;
int LastPos;

if(FullName==NULL) return(NULL);

LastPos=strlen(FullName);
NameStep=FullName+LastPos+1;
while(NameStep>FullName)
	{
	NameStep--;

	if(*NameStep=='/' || *NameStep=='\\' || *NameStep==':')
		break;
	if(*NameStep=='.')
		return(NameStep);
	}

return(FullName+LastPos);
}

////////////////////////////////////////////////////////////////////


char Verbosity = 0;

void PrintHeader(void)
{
char HdrPrinted=0;

  if(Verbosity>=0 && HdrPrinted==0)
    {
    puts("\n\r <<< FILTER >>> Mask picture filtering (c)1997-2024 F&TSoft ");
    HdrPrinted = 1;
    }
}



const TImageFileHandler *FindImgHandler(const char *OutFormat)
{
const TImageFileHandler *SavePicture_XXX;
  for(SavePicture_XXX=TImageFileHandler::first(); SavePicture_XXX!=NULL; SavePicture_XXX=SavePicture_XXX->next())
  {
    if(SavePicture_XXX->SavePicture!=NULL)
    {
      const char *ext = SavePicture_XXX->extension();

      if(ext!=NULL)
      {
        if(*ext=='.') ext++;
	size_t i = strlen(ext);
        if(!stricmp(OutFormat,ext))	// Exact match
        {
          return SavePicture_XXX;
	}
	if(!strnicmp(OutFormat,ext,i))
        {
	  if(OutFormat[i]=='#')
	  {
	    if(!stricmp(OutFormat+i+1,SavePicture_XXX->description()))
	    {
              return SavePicture_XXX;
	    }
	  }
        }
      }
    }
  }
  return NULL;
}


/////////////////////Main CODE starts here/////////////////////////////////


int main(int argc,char *argv[])
{
Image I1;
const char *InputImg=NULL, *OutputImg=NULL;
const char *s;
TImageFileHandler *LoadPicture_XXX;
int i;
int MaskSize = 3;
bool Conv2Gray = false;
int Error = 0;
char Filter = 0;
const char *OutFormat=NULL;

	/* Parse Arguments */
for(i=1;i<argc;i++)
  {
  s=argv[i];
  if(s==NULL) continue;
  if( *s==0 ) continue;

  if(*s=='-' || *s=='/')
    {
    if(strcmp(s+1,"help")==0 || strcmp(s+1,"-help")==0 || strcmp(s+1,"?")==0)
      {
        PrintHeader();
        printf("\n");
        for(LoadPicture_XXX=TImageFileHandler::first();LoadPicture_XXX!=NULL;LoadPicture_XXX=LoadPicture_XXX->next())
	  {
	  printf("%s %s%s; ",LoadPicture_XXX->extension(),
			     LoadPicture_XXX->LoadPicture==NULL?"":"R",
			     LoadPicture_XXX->SavePicture==NULL?"":"W");
	  }
	printf(//"\n/NoScale      - means truncating image data"
	       "\n/Format \"str\" - specify output format"
	       "\n/Gaus         - switch gausian filter"
	       "\n/Gray         - discards all color informations"
	       //"\n/SEPARATE[R|G|B] - remove one channel from true color images"
	       "\n/MaskSize n  - filter mask extent n*n"
	       "\n/Mask         - switch mask filter"
	       "\n/Median       - switch median filter"
	       "\n/s            - decrease verbosity level"
	       "\n");
        return(0);
      }
     if(strcmp(s+1,"Format")==0 || strcmp(s+1,"format")==0)
     {
       ++i;
       if(i>=argc) break;
       OutFormat = argv[i];
       continue;
     }
     if(strcmp(s+1,"MaskSize") == 0)
     {
       MaskSize = atoi(argv[++i]);
       continue;
     }
     if(strcmp(s+1,"s") == 0)
     {
      Verbosity = -1;
      continue;
     }
     if(strcmp(s+1,"Gaus") == 0)
     {             
       Filter = 2;
       continue;
     }
     if(strcmp(s+1,"Gray") == 0)
     {
       Conv2Gray = true;
       continue;
     }
     if(strcmp(s+1,"Mask") == 0)
     {
       Filter = 0;
       continue;
     }
     if(strcmp(s+1,"Median") == 0)
     {
       Filter = 1;
       continue;
     }
    }

  if(InputImg==NULL)
     InputImg=s;
  else
     if(OutputImg==NULL) OutputImg=s;
  }
	/* End of reading arguments */

  PrintHeader();
  if(Verbosity>=0) printf("\rLoading");
  //MarkTime=GetInterval();

  //for(i=1;i<=10;i++)
  I1 = LoadPicture(InputImg);
  if(I1.Raster==NULL && I1.VecImage==NULL)
	{
	printf("\n\rCannot load input picture:\"%s\" Error %d",InputImg,Error);
	goto End;
	}

  if(Conv2Gray)
  {
    if(Verbosity>=0) printf("\rConverting to gray ");
    Convert2Gray(&I1);
  }

  //MarkTime=GetInterval();
  
  switch(Filter)  
  {
    case 0: if(Verbosity>=0) printf("\rMask filtering");
            I1 = Mask(&I1,MaskSize);
            break;
    case 1: if(Verbosity>=0) printf("\rMedian filtering");
            I1 = Median(I1,MaskSize);
            break;
    case 2: if(Verbosity>=0) printf("\rGausian filtering");
            {
              Image *Im = &I1;
              while(Im != NULL)
              {
                if(MaskSize>=0)
                {
                  GausFunc(Im->Raster,gfGaus, MaskSize);
                }
                Im = Im->Next;
              }
            }
            break;
   default: printf("\rUnknown filter?");
            break;
  }

  if(Verbosity>=0) printf("\rSaving        ");

  {
    const TImageFileHandler *SavePicture_XXX;
    if(OutFormat==NULL)
    {				//No format requested
      SavePicture_XXX = FindImgHandler(ReadExt(OutputImg));
    }
    else
    {
      SavePicture_XXX = FindImgHandler(OutFormat);
    }

    if(SavePicture_XXX != NULL)
    {
      if((SavePicture_XXX->Flags&FILE_FORMAT_CAP_EXIF)==0 && HasExif(&I1))
         AutoOrient(&I1);
      Error = SavePicture_XXX->SavePicture(OutputImg,I1);
    }
    else
        Error = 0xFFFF;
  }

  if(Error)
  {
    printf("\n\rCannot save output picture:\"%s\" Error %d",OutputImg,Error);
  }
  else
  {
    if(Verbosity>=0)
    {
      //printf("time : %f",abs(GetInterval()-MarkTime)/18.2);
      puts("\rOK     ");
    }
  }

End:
  return(Error);
}
